From 1dc443debae623d0181fb0064aa675e4b07cc420 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Fri, 30 Jan 2004 15:52:47 +0000 Subject: [PATCH] bitkeeper revision 1.697 (401a7dcfLSasqkAaMngsKdiVm_puVw) config.h, ide-cd.c, dom0_ops.c, pci-pc.c: Fix stack overflows in Xen. --- xen/arch/i386/pci-pc.c | 33 +++++-- xen/common/dom0_ops.c | 193 ++++++++++++++++++++------------------ xen/drivers/ide/ide-cd.c | 17 +++- xen/include/xeno/config.h | 2 +- 4 files changed, 141 insertions(+), 104 deletions(-) diff --git a/xen/arch/i386/pci-pc.c b/xen/arch/i386/pci-pc.c index d63a54a79c..bb5ba8d299 100644 --- a/xen/arch/i386/pci-pc.c +++ b/xen/arch/i386/pci-pc.c @@ -442,21 +442,36 @@ static struct pci_ops pci_direct_conf2 = { static int __devinit pci_sanity_check(struct pci_ops *o) { u16 x; - struct pci_bus bus; /* Fake bus and device */ - struct pci_dev dev; + struct pci_bus *bus; /* Fake bus and device */ + struct pci_dev *dev; + int ret = 0; if (pci_probe & PCI_NO_CHECKS) return 1; - bus.number = 0; - dev.bus = &bus; - for(dev.devfn=0; dev.devfn < 0x100; dev.devfn++) - if ((!o->read_word(&dev, PCI_CLASS_DEVICE, &x) && + + bus = kmalloc(sizeof(*bus), GFP_KERNEL); + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if ( (bus == NULL) || (dev == NULL) ) + goto out; + + bus->number = 0; + dev->bus = bus; + for(dev->devfn=0; dev->devfn < 0x100; dev->devfn++) + if ((!o->read_word(dev, PCI_CLASS_DEVICE, &x) && (x == PCI_CLASS_BRIDGE_HOST || x == PCI_CLASS_DISPLAY_VGA)) || - (!o->read_word(&dev, PCI_VENDOR_ID, &x) && + (!o->read_word(dev, PCI_VENDOR_ID, &x) && (x == PCI_VENDOR_ID_INTEL || x == PCI_VENDOR_ID_COMPAQ))) - return 1; + { + ret = 1; + break; + } + out: + if ( bus != NULL ) + kfree(bus); + if ( dev != NULL) + kfree(dev); DBG("PCI: Sanity check failed\n"); - return 0; + return ret; } static struct pci_ops * __devinit pci_check_direct(void) diff --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c index d1a2983ea6..b3aa93ca3b 100644 --- a/xen/common/dom0_ops.c +++ b/xen/common/dom0_ops.c @@ -59,27 +59,36 @@ static void read_msr_for(void *unused) long do_dom0_op(dom0_op_t *u_dom0_op) { long ret = 0; - dom0_op_t op; + dom0_op_t *op; if ( !IS_PRIV(current) ) return -EPERM; - if ( copy_from_user(&op, u_dom0_op, sizeof(op)) ) - return -EFAULT; + if ( (op = kmalloc(sizeof(*op), GFP_KERNEL)) == NULL ) + return -ENOMEM; - if ( op.interface_version != DOM0_INTERFACE_VERSION ) - return -EACCES; + if ( copy_from_user(op, u_dom0_op, sizeof(*op)) ) + { + ret = -EFAULT; + goto out; + } + + if ( op->interface_version != DOM0_INTERFACE_VERSION ) + { + ret = -EACCES; + goto out; + } - switch ( op.cmd ) + switch ( op->cmd ) { case DOM0_BUILDDOMAIN: { - struct task_struct * p = find_domain_by_id(op.u.builddomain.domain); + struct task_struct * p = find_domain_by_id(op->u.builddomain.domain); ret = -EINVAL; if ( p != NULL ) { - ret = final_setup_guestos(p, &op.u.builddomain); + ret = final_setup_guestos(p, &op->u.builddomain); put_task_struct(p); } } @@ -87,7 +96,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op) case DOM0_STARTDOMAIN: { - struct task_struct * p = find_domain_by_id(op.u.startdomain.domain); + struct task_struct * p = find_domain_by_id(op->u.startdomain.domain); ret = -EINVAL; if ( p != NULL ) { @@ -104,7 +113,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op) case DOM0_STOPDOMAIN: { - ret = stop_other_domain(op.u.stopdomain.domain); + ret = stop_other_domain(op->u.stopdomain.domain); } break; @@ -125,13 +134,13 @@ long do_dom0_op(dom0_op_t *u_dom0_op) if ( p == NULL ) goto exit_create; - if ( op.u.createdomain.name[0] ) + if ( op->u.createdomain.name[0] ) { - strncpy (p->name, op.u.createdomain.name, MAX_DOMAIN_NAME); + strncpy (p->name, op->u.createdomain.name, MAX_DOMAIN_NAME); p->name[MAX_DOMAIN_NAME - 1] = 0; } - ret = alloc_new_dom_mem(p, op.u.createdomain.memory_kb); + ret = alloc_new_dom_mem(p, op->u.createdomain.memory_kb); if ( ret != 0 ) { __kill_domain(p); @@ -140,8 +149,8 @@ long do_dom0_op(dom0_op_t *u_dom0_op) ret = p->domain; - op.u.createdomain.domain = ret; - copy_to_user(u_dom0_op, &op, sizeof(op)); + op->u.createdomain.domain = ret; + copy_to_user(u_dom0_op, op, sizeof(*op)); exit_create: spin_unlock_irq(&create_dom_lock); @@ -150,16 +159,16 @@ long do_dom0_op(dom0_op_t *u_dom0_op) case DOM0_DESTROYDOMAIN: { - unsigned int dom = op.u.destroydomain.domain; - int force = op.u.destroydomain.force; + unsigned int dom = op->u.destroydomain.domain; + int force = op->u.destroydomain.force; ret = (dom == IDLE_DOMAIN_ID) ? -EPERM : kill_other_domain(dom, force); } break; case DOM0_PINCPUDOMAIN: { - struct task_struct * p = find_domain_by_id(op.u.pincpudomain.domain); - int cpu = op.u.pincpudomain.cpu; + struct task_struct * p = find_domain_by_id(op->u.pincpudomain.domain); + int cpu = op->u.pincpudomain.cpu; ret = -EINVAL; if ( p != NULL ) { @@ -197,18 +206,18 @@ long do_dom0_op(dom0_op_t *u_dom0_op) case DOM0_BVTCTL: { - unsigned long ctx_allow = op.u.bvtctl.ctx_allow; + unsigned long ctx_allow = op->u.bvtctl.ctx_allow; ret = sched_bvtctl(ctx_allow); } break; case DOM0_ADJUSTDOM: { - unsigned int dom = op.u.adjustdom.domain; - unsigned long mcu_adv = op.u.adjustdom.mcu_adv; - unsigned long warp = op.u.adjustdom.warp; - unsigned long warpl = op.u.adjustdom.warpl; - unsigned long warpu = op.u.adjustdom.warpu; + unsigned int dom = op->u.adjustdom.domain; + unsigned long mcu_adv = op->u.adjustdom.mcu_adv; + unsigned long warp = op->u.adjustdom.warp; + unsigned long warpl = op->u.adjustdom.warpl; + unsigned long warpu = op->u.adjustdom.warpu; ret = -EPERM; if ( dom != IDLE_DOMAIN_ID ) @@ -219,10 +228,10 @@ long do_dom0_op(dom0_op_t *u_dom0_op) case DOM0_GETMEMLIST: { int i; - struct task_struct *p = find_domain_by_id(op.u.getmemlist.domain); - unsigned long max_pfns = op.u.getmemlist.max_pfns; + struct task_struct *p = find_domain_by_id(op->u.getmemlist.domain); + unsigned long max_pfns = op->u.getmemlist.max_pfns; unsigned long pfn; - unsigned long *buffer = op.u.getmemlist.buffer; + unsigned long *buffer = op->u.getmemlist.buffer; struct list_head *list_ent; ret = -EINVAL; @@ -246,8 +255,8 @@ long do_dom0_op(dom0_op_t *u_dom0_op) } spin_unlock(&p->page_list_lock); - op.u.getmemlist.num_pfns = i; - copy_to_user(u_dom0_op, &op, sizeof(op)); + op->u.getmemlist.num_pfns = i; + copy_to_user(u_dom0_op, op, sizeof(*op)); put_task_struct(p); } @@ -263,7 +272,8 @@ long do_dom0_op(dom0_op_t *u_dom0_op) read_lock_irqsave (&tasklist_lock, flags); while ( (p = p->next_task) != &idle0_task ) - if ( !is_idle_task(p) && (p->domain >= op.u.getdomaininfo.domain) ) + if ( !is_idle_task(p) && + (p->domain >= op->u.getdomaininfo.domain) ) break; if ( p == &idle0_task ) @@ -272,76 +282,78 @@ long do_dom0_op(dom0_op_t *u_dom0_op) } else { - op.u.getdomaininfo.domain = p->domain; - strcpy (op.u.getdomaininfo.name, p->name); - op.u.getdomaininfo.processor = p->processor; - op.u.getdomaininfo.has_cpu = p->has_cpu; - op.u.getdomaininfo.state = DOMSTATE_ACTIVE; + op->u.getdomaininfo.domain = p->domain; + strcpy (op->u.getdomaininfo.name, p->name); + op->u.getdomaininfo.processor = p->processor; + op->u.getdomaininfo.has_cpu = p->has_cpu; + op->u.getdomaininfo.state = DOMSTATE_ACTIVE; if ( (p->state == TASK_STOPPED) || (p->state == TASK_DYING) ) - op.u.getdomaininfo.state = DOMSTATE_STOPPED; - op.u.getdomaininfo.hyp_events = p->hyp_events; - op.u.getdomaininfo.mcu_advance = p->mcu_advance; - op.u.getdomaininfo.tot_pages = p->tot_pages; - op.u.getdomaininfo.cpu_time = p->cpu_time; - op.u.getdomaininfo.shared_info_frame = + op->u.getdomaininfo.state = DOMSTATE_STOPPED; + op->u.getdomaininfo.hyp_events = p->hyp_events; + op->u.getdomaininfo.mcu_advance = p->mcu_advance; + op->u.getdomaininfo.tot_pages = p->tot_pages; + op->u.getdomaininfo.cpu_time = p->cpu_time; + op->u.getdomaininfo.shared_info_frame = __pa(p->shared_info) >> PAGE_SHIFT; if ( p->state == TASK_STOPPED ) { rmb(); /* Ensure that we see saved register state. */ - op.u.getdomaininfo.ctxt.flags = 0; - memcpy(&op.u.getdomaininfo.ctxt.i386_ctxt, + op->u.getdomaininfo.ctxt.flags = 0; + memcpy(&op->u.getdomaininfo.ctxt.i386_ctxt, &p->shared_info->execution_context, sizeof(p->shared_info->execution_context)); if ( p->flags & PF_DONEFPUINIT ) - op.u.getdomaininfo.ctxt.flags |= ECF_I387_VALID; - memcpy(&op.u.getdomaininfo.ctxt.i387_ctxt, + op->u.getdomaininfo.ctxt.flags |= ECF_I387_VALID; + memcpy(&op->u.getdomaininfo.ctxt.i387_ctxt, &p->thread.i387, sizeof(p->thread.i387)); - memcpy(&op.u.getdomaininfo.ctxt.trap_ctxt, + memcpy(&op->u.getdomaininfo.ctxt.trap_ctxt, p->thread.traps, sizeof(p->thread.traps)); if ( (p->thread.fast_trap_desc.a == 0) && (p->thread.fast_trap_desc.b == 0) ) - op.u.getdomaininfo.ctxt.fast_trap_idx = 0; + op->u.getdomaininfo.ctxt.fast_trap_idx = 0; else - op.u.getdomaininfo.ctxt.fast_trap_idx = + op->u.getdomaininfo.ctxt.fast_trap_idx = p->thread.fast_trap_idx; - op.u.getdomaininfo.ctxt.ldt_base = p->mm.ldt_base; - op.u.getdomaininfo.ctxt.ldt_ents = p->mm.ldt_ents; - op.u.getdomaininfo.ctxt.gdt_ents = 0; + op->u.getdomaininfo.ctxt.ldt_base = p->mm.ldt_base; + op->u.getdomaininfo.ctxt.ldt_ents = p->mm.ldt_ents; + op->u.getdomaininfo.ctxt.gdt_ents = 0; if ( GET_GDT_ADDRESS(p) == GDT_VIRT_START ) { for ( i = 0; i < 16; i++ ) - op.u.getdomaininfo.ctxt.gdt_frames[i] = + op->u.getdomaininfo.ctxt.gdt_frames[i] = l1_pgentry_to_pagenr(p->mm.perdomain_pt[i]); - op.u.getdomaininfo.ctxt.gdt_ents = + op->u.getdomaininfo.ctxt.gdt_ents = (GET_GDT_ENTRIES(p) + 1) >> 3; } - op.u.getdomaininfo.ctxt.ring1_ss = p->thread.ss1; - op.u.getdomaininfo.ctxt.ring1_esp = p->thread.esp1; - op.u.getdomaininfo.ctxt.pt_base = + op->u.getdomaininfo.ctxt.ring1_ss = p->thread.ss1; + op->u.getdomaininfo.ctxt.ring1_esp = p->thread.esp1; + op->u.getdomaininfo.ctxt.pt_base = pagetable_val(p->mm.pagetable); - memcpy(op.u.getdomaininfo.ctxt.debugreg, + memcpy(op->u.getdomaininfo.ctxt.debugreg, p->thread.debugreg, sizeof(p->thread.debugreg)); - op.u.getdomaininfo.ctxt.event_callback_cs = p->event_selector; - op.u.getdomaininfo.ctxt.event_callback_eip = p->event_address; - op.u.getdomaininfo.ctxt.failsafe_callback_cs = + op->u.getdomaininfo.ctxt.event_callback_cs = + p->event_selector; + op->u.getdomaininfo.ctxt.event_callback_eip = + p->event_address; + op->u.getdomaininfo.ctxt.failsafe_callback_cs = p->failsafe_selector; - op.u.getdomaininfo.ctxt.failsafe_callback_eip = + op->u.getdomaininfo.ctxt.failsafe_callback_eip = p->failsafe_address; } } read_unlock_irqrestore(&tasklist_lock, flags); - copy_to_user(u_dom0_op, &op, sizeof(op)); + copy_to_user(u_dom0_op, op, sizeof(*op)); } break; case DOM0_GETPAGEFRAMEINFO: { struct pfn_info *page; - unsigned long pfn = op.u.getpageframeinfo.pfn; - unsigned int dom = op.u.getpageframeinfo.domain; + unsigned long pfn = op->u.getpageframeinfo.pfn; + unsigned int dom = op->u.getpageframeinfo.domain; struct task_struct *p; ret = -EINVAL; @@ -356,17 +368,17 @@ long do_dom0_op(dom0_op_t *u_dom0_op) { ret = 0; - op.u.getpageframeinfo.type = NONE; + op->u.getpageframeinfo.type = NONE; if ( (page->type_and_flags & PGT_count_mask) != 0 ) { switch ( page->type_and_flags & PGT_type_mask ) { case PGT_l1_page_table: - op.u.getpageframeinfo.type = L1TAB; + op->u.getpageframeinfo.type = L1TAB; break; case PGT_l2_page_table: - op.u.getpageframeinfo.type = L2TAB; + op->u.getpageframeinfo.type = L2TAB; break; } } @@ -376,38 +388,38 @@ long do_dom0_op(dom0_op_t *u_dom0_op) put_task_struct(p); - copy_to_user(u_dom0_op, &op, sizeof(op)); + copy_to_user(u_dom0_op, op, sizeof(*op)); } break; case DOM0_IOPL: { extern long do_iopl(unsigned int, unsigned int); - ret = do_iopl(op.u.iopl.domain, op.u.iopl.iopl); + ret = do_iopl(op->u.iopl.domain, op->u.iopl.iopl); } break; case DOM0_MSR: { - if ( op.u.msr.write ) + if ( op->u.msr.write ) { - msr_cpu_mask = op.u.msr.cpu_mask; - msr_addr = op.u.msr.msr; - msr_lo = op.u.msr.in1; - msr_hi = op.u.msr.in2; + msr_cpu_mask = op->u.msr.cpu_mask; + msr_addr = op->u.msr.msr; + msr_lo = op->u.msr.in1; + msr_hi = op->u.msr.in2; smp_call_function(write_msr_for, NULL, 1, 1); write_msr_for(NULL); } else { - msr_cpu_mask = op.u.msr.cpu_mask; - msr_addr = op.u.msr.msr; + msr_cpu_mask = op->u.msr.cpu_mask; + msr_addr = op->u.msr.msr; smp_call_function(read_msr_for, NULL, 1, 1); read_msr_for(NULL); - op.u.msr.out1 = msr_lo; - op.u.msr.out2 = msr_hi; - copy_to_user(u_dom0_op, &op, sizeof(op)); + op->u.msr.out1 = msr_lo; + op->u.msr.out2 = msr_hi; + copy_to_user(u_dom0_op, op, sizeof(*op)); } ret = 0; } @@ -416,27 +428,28 @@ long do_dom0_op(dom0_op_t *u_dom0_op) case DOM0_DEBUG: { extern void pdb_do_debug(dom0_op_t *); - pdb_do_debug(&op); - copy_to_user(u_dom0_op, &op, sizeof(op)); + pdb_do_debug(op); + copy_to_user(u_dom0_op, op, sizeof(*op)); ret = 0; } break; case DOM0_SETTIME: { - do_settime(op.u.settime.secs, - op.u.settime.usecs, - op.u.settime.system_time); + do_settime(op->u.settime.secs, + op->u.settime.usecs, + op->u.settime.system_time); ret = 0; } break; case DOM0_READCONSOLE: { - extern long read_console_ring(unsigned long, unsigned int, unsigned int); - ret = read_console_ring(op.u.readconsole.str, - op.u.readconsole.count, - op.u.readconsole.cmd); + extern long read_console_ring(unsigned long, + unsigned int, unsigned int); + ret = read_console_ring(op->u.readconsole.str, + op->u.readconsole.count, + op->u.readconsole.cmd); } break; @@ -445,5 +458,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op) } + out: + kfree(op); return ret; } diff --git a/xen/drivers/ide/ide-cd.c b/xen/drivers/ide/ide-cd.c index 37302850e5..5bcc450b5c 100644 --- a/xen/drivers/ide/ide-cd.c +++ b/xen/drivers/ide/ide-cd.c @@ -818,7 +818,7 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector, (SECTOR_BUFFER_SIZE >> SECTOR_BITS) - info->nsectors_buffered); - char *dest; + char *dest, *dum; /* If we couldn't get a buffer, don't try to buffer anything... */ if (info->buffer == NULL) @@ -839,11 +839,12 @@ static void cdrom_buffer_sectors (ide_drive_t *drive, unsigned long sector, } /* Throw away any remaining data. */ + dum = kmalloc(SECTOR_SIZE, GFP_ATOMIC); while (sectors_to_transfer > 0) { - char dum[SECTOR_SIZE]; - atapi_input_bytes (drive, dum, sizeof (dum)); + atapi_input_bytes (drive, dum, SECTOR_SIZE); --sectors_to_transfer; } + kfree(dum); } /* @@ -896,6 +897,7 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive) struct cdrom_info *info = drive->driver_data; int i, dma = info->dma, dma_error = 0; ide_startstop_t startstop; + char *dum; struct request *rq = HWGROUP(drive)->rq; @@ -965,15 +967,20 @@ static ide_startstop_t cdrom_read_intr (ide_drive_t *drive) nskip = MIN ((int)(rq->current_nr_sectors - (rq->bh->b_size >> SECTOR_BITS)), sectors_to_transfer); + if ( (dum = kmalloc(SECTOR_SIZE, GFP_ATOMIC)) == NULL ) + { + cdrom_end_request (0, drive); + return ide_stopped; + } while (nskip > 0) { /* We need to throw away a sector. */ - char dum[SECTOR_SIZE]; - atapi_input_bytes (drive, dum, sizeof (dum)); + atapi_input_bytes (drive, dum, SECTOR_SIZE); --rq->current_nr_sectors; --nskip; --sectors_to_transfer; } + kfree(dum); /* Now loop while we still have data to read from the drive. */ while (sectors_to_transfer > 0) { diff --git a/xen/include/xeno/config.h b/xen/include/xeno/config.h index 6dc740405d..530e4ce238 100644 --- a/xen/include/xeno/config.h +++ b/xen/include/xeno/config.h @@ -145,10 +145,10 @@ #define capable(_c) 0 +#define STACK_GUARD #ifndef NDEBUG #define DPRINTK(_f, _a...) printk("(file=%s, line=%d) " _f, \ __FILE__, __LINE__, ## _a) -#define STACK_GUARD #else #define DPRINTK(_f, _a...) ((void)0) #endif -- 2.30.2